<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>聊天功能测试</title>
    <link rel="stylesheet" href="css/websocket-test.css">
</head>
<body>
    <div class="container">
        <h1>聊天功能测试</h1>
        <div class="notification notification-info">
            此页面用于测试一对一聊天、文字消息、已读回执和输入指示器功能
        </div>

        <div class="row">
            <div class="col" style="max-width: 300px;">
                <div class="card">
                    <h2 class="card-header">连接设置</h2>
                    <div class="form-group">
                        <label for="endpoint">WebSocket端点</label>
                        <input type="text" id="endpoint" value="/ChatMessageServer" placeholder="例如 /ChatMessageServer">
                    </div>
                    <div class="form-group">
                        <label for="username">您的用户名</label>
                        <input type="text" id="username" placeholder="输入用户名">
                    </div>
                    <div class="form-group">
                        <button id="connectBtn" class="btn w-100">连接</button>
                        <button id="disconnectBtn" class="btn btn-secondary w-100 mt-2" disabled>断开</button>
                    </div>

                    <div class="mt-3">
                        <div class="d-flex align-items-center">
                            <div id="statusIndicator" class="status-indicator status-offline"></div>
                            <span id="statusText">未连接</span>
                        </div>
                    </div>
                </div>

                <div class="card" id="friendsCard" style="display: none;">
                    <h2 class="card-header">联系人</h2>
                    <div class="form-group">
                        <label for="newFriend">添加联系人</label>
                        <div class="d-flex">
                            <input type="text" id="newFriend" placeholder="输入用户名">
                            <button id="addFriendBtn" class="btn btn-secondary" style="margin-left: 5px;">添加</button>
                        </div>
                    </div>
                    <ul id="friendList" class="friend-list">
                        <!-- 联系人列表将在此显示 -->
                    </ul>
                </div>
            </div>

            <div class="col" style="flex-grow: 2;">
                <div class="card" id="chatCard" style="display: none;">
                    <h2 class="card-header d-flex justify-content-between align-items-center">
                        <span>与 <span id="receiverName">-</span> 聊天中</span>
                        <span id="typingIndicator" style="font-size: 0.8em; display: none;">对方正在输入...</span>
                    </h2>
                    <div id="messageContainer" class="message-list"></div>

                    <div class="mt-2 d-flex">
                        <textarea id="messageInput" placeholder="输入消息..." rows="2" style="flex-grow: 1;"></textarea>
                        <button id="sendBtn" class="btn" style="margin-left: 5px;">发送</button>
                    </div>

                    <div class="d-flex mt-2">
                        <label class="d-flex align-items-center" style="margin-right: 10px;">
                            <input type="checkbox" id="readReceiptCb" checked>
                            <span style="margin-left: 5px;">发送已读回执</span>
                        </label>
                        <label class="d-flex align-items-center">
                            <input type="checkbox" id="typingIndicatorCb" checked>
                            <span style="margin-left: 5px;">发送输入指示器</span>
                        </label>
                    </div>
                </div>

                <div class="card" id="welcomeCard">
                    <h2 class="card-header">欢迎使用</h2>
                    <div class="text-center p-5">
                        <h3>请先连接服务器并选择联系人开始聊天</h3>
                        <p class="text-muted">您可以在左侧添加联系人并点击他们的名字开始聊天</p>
                    </div>
                </div>
            </div>
        </div>

        <div class="row">
            <div class="col">
                <div class="card">
                    <h2 class="card-header d-flex justify-content-between align-items-center">
                        <span>连接日志</span>
                        <button id="clearLogsBtn" class="btn btn-small btn-secondary">清空日志</button>
                    </h2>
                    <div id="connectionLogs" class="message-list" style="height: 200px;"></div>
                </div>
            </div>
        </div>
    </div>

    <!-- 脚本引入 -->
    <script src="js/websocket-client.js"></script>
    <script>
    // DOM元素
    const connectBtn = document.getElementById('connectBtn');
    const disconnectBtn = document.getElementById('disconnectBtn');
    const endpointInput = document.getElementById('endpoint');
    const usernameInput = document.getElementById('username');
    const statusIndicator = document.getElementById('statusIndicator');
    const statusText = document.getElementById('statusText');
    const friendsCard = document.getElementById('friendsCard');
    const chatCard = document.getElementById('chatCard');
    const welcomeCard = document.getElementById('welcomeCard');
    const friendList = document.getElementById('friendList');
    const newFriendInput = document.getElementById('newFriend');
    const addFriendBtn = document.getElementById('addFriendBtn');
    const receiverNameSpan = document.getElementById('receiverName');
    const messageContainer = document.getElementById('messageContainer');
    const messageInput = document.getElementById('messageInput');
    const sendBtn = document.getElementById('sendBtn');
    const readReceiptCb = document.getElementById('readReceiptCb');
    const typingIndicatorCb = document.getElementById('typingIndicatorCb');
    const typingIndicator = document.getElementById('typingIndicator');
    const connectionLogs = document.getElementById('connectionLogs');
    const clearLogsBtn = document.getElementById('clearLogsBtn');

    // 变量
    let wsClient = null;
    let currentReceiver = null;
    let friends = [];
    let conversations = {};
    let typingTimeout = null;

    // 页面初始化
    function init() {
        // 从URL参数获取用户名和端点
        const urlParams = new URLSearchParams(window.location.search);
        if (urlParams.has('username')) {
            usernameInput.value = urlParams.get('username');
        }
        if (urlParams.has('endpoint')) {
            endpointInput.value = urlParams.get('endpoint');
        }

        // 绑定事件
        connectBtn.addEventListener('click', connect);
        disconnectBtn.addEventListener('click', disconnect);
        addFriendBtn.addEventListener('click', addFriend);
        sendBtn.addEventListener('click', sendMessage);
        clearLogsBtn.addEventListener('click', clearLogs);

        // 输入框事件
        messageInput.addEventListener('keydown', function(e) {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendMessage();
            }
        });

        messageInput.addEventListener('input', handleTyping);
    }

    // 连接WebSocket
    function connect() {
        const endpoint = endpointInput.value.trim();
        const username = usernameInput.value.trim();

        if (!endpoint) {
            addLog('错误', 'WebSocket端点不能为空');
            return;
        }

        if (!username) {
            addLog('错误', '用户名不能为空');
            return;
        }

        // 禁用连接按钮
        connectBtn.disabled = true;
        addLog('信息', `尝试连接到 ${endpoint}...`);

        try {
            // 创建WebSocket客户端
            wsClient = new WebSocketClient(endpoint, username, {
                onConnect: handleConnect,
                onDisconnect: handleDisconnect,
                onMessage: handleMessage,
                onError: handleError,
                onReconnect: handleReconnect,
                onReconnectFailed: handleReconnectFailed
            });

            // 连接
            wsClient.connect();
        } catch (error) {
            addLog('错误', `连接初始化失败: ${error.message}`);
            connectBtn.disabled = false;
        }
    }

    // 处理连接成功
    function handleConnect() {
        // 更新UI状态
        statusIndicator.className = 'status-indicator status-online';
        statusText.textContent = '已连接';
        connectBtn.disabled = true;
        disconnectBtn.disabled = false;
        
        // 显示联系人卡片
        friendsCard.style.display = 'block';
        
        // 添加一些默认好友用于演示
        if (friends.length === 0) {
            friends.push('user1', 'user2', 'admin');
            refreshFriendList();
        }

        addLog('成功', '连接已建立');
    }

    // 处理连接断开
    function handleDisconnect(event) {
        // 更新UI状态
        statusIndicator.className = 'status-indicator status-offline';
        statusText.textContent = '已断开';
        connectBtn.disabled = false;
        disconnectBtn.disabled = true;
        
        // 隐藏联系人和聊天卡片
        friendsCard.style.display = 'none';
        chatCard.style.display = 'none';
        welcomeCard.style.display = 'block';
        
        // 清空当前接收者
        currentReceiver = null;

        addLog('信息', `连接已断开${event.code ? (' (代码: ' + event.code + ')') : ''}`);
    }

    // 处理接收消息
    function handleMessage(message) {
        addLog('收到', JSON.stringify(message));
        
        // 根据消息类型处理
        switch (message.type) {
            case 'chat':
                handleChatMessage(message);
                break;
            case 'typing':
                handleTypingMessage(message);
                break;
            case 'read_receipt':
                handleReadReceipt(message);
                break;
            case 'friend_status':
                handleFriendStatus(message);
                break;
            case 'system_notification':
            case 'system':
                handleSystemMessage(message);
                break;
            case 'error':
                handleErrorMessage(message);
                break;
        }
    }

    // 处理聊天消息
    function handleChatMessage(message) {
        const sender = message.fromUser;
        
        // 确保有会话
        if (!conversations[sender]) {
            conversations[sender] = [];
        }
        
        // 添加到会话
        conversations[sender].push(message);
        
        // 如果是当前会话，显示消息
        if (currentReceiver === sender) {
            displayMessage(message);
            
            // 发送已读回执
            if (readReceiptCb.checked) {
                setTimeout(() => {
                    wsClient.sendReadReceipt(sender, message.messageId);
                }, 1000);
            }
        } else {
            // 如果不是当前会话，更新好友列表中的未读提示
            highlightFriendWithUnread(sender);
        }
    }

    // 处理输入指示器消息
    function handleTypingMessage(message) {
        const sender = message.fromUser;
        
        if (currentReceiver === sender) {
            // 显示"正在输入"指示器
            typingIndicator.style.display = 'block';
            
            // 3秒后隐藏
            setTimeout(() => {
                typingIndicator.style.display = 'none';
            }, 3000);
        }
    }

    // 处理已读回执
    function handleReadReceipt(message) {
        const sender = message.fromUser;
        const messageId = message.relatedMessageId;
        
        // 找到并更新消息状态
        if (conversations[sender]) {
            for (let i = 0; i < conversations[sender].length; i++) {
                if (conversations[sender][i].messageId === messageId) {
                    conversations[sender][i].read = true;
                    
                    // 如果是当前会话，更新UI
                    if (currentReceiver === sender) {
                        const msgElement = document.querySelector(`.message-item[data-id="${messageId}"]`);
                        if (msgElement) {
                            const statusEl = msgElement.querySelector('.message-status');
                            if (statusEl) {
                                statusEl.textContent = '已读';
                                statusEl.className = 'message-status text-success';
                            }
                        }
                    }
                    break;
                }
            }
        }
    }

    // 处理好友状态变更
    function handleFriendStatus(message) {
        const friendName = message.fromUser;
        const status = message.content; // 'online' 或 'offline'
        
        // 更新好友列表
        updateFriendStatus(friendName, status === 'online');
    }

    // 处理系统消息
    function handleSystemMessage(message) {
        // 系统通知可以在UI中显示为特殊消息
        addLog('系统', message.content);
    }

    // 处理错误消息
    function handleErrorMessage(message) {
        addLog('错误', message.content);
    }

    // 处理错误
    function handleError(error) {
        addLog('错误', error.message || '发生未知错误');
    }

    // 处理重连尝试
    function handleReconnect(attempt, maxAttempts) {
        statusText.textContent = `正在重连 (${attempt}/${maxAttempts})`;
        statusText.className = 'animate-blink';
        addLog('信息', `尝试重连 (${attempt}/${maxAttempts})...`);
    }

    // 处理重连失败
    function handleReconnectFailed() {
        statusText.textContent = '重连失败';
        statusText.className = '';
        connectBtn.disabled = false;
        addLog('错误', '重连失败，已达到最大尝试次数');
    }

    // 主动断开连接
    function disconnect() {
        if (wsClient) {
            wsClient.disconnect();
        }
    }

    // 发送消息
    function sendMessage() {
        if (!wsClient || !currentReceiver) {
            return;
        }
        
        const content = messageInput.value.trim();
        if (!content) {
            return;
        }
        
        // 发送消息
        const messageId = wsClient.sendTextMessage(currentReceiver, content);
        
        // 创建消息对象
        const message = {
            type: 'chat',
            fromUser: wsClient.username,
            toUser: currentReceiver,
            contentType: 'text',
            content: content,
            messageId: messageId,
            timestamp: Date.now()
        };
        
        // 添加到会话
        if (!conversations[currentReceiver]) {
            conversations[currentReceiver] = [];
        }
        conversations[currentReceiver].push(message);
        
        // 显示消息
        displayMessage(message);
        
        // 清空输入框
        messageInput.value = '';
    }

    // 处理输入事件，发送"正在输入"指示器
    function handleTyping() {
        if (!wsClient || !currentReceiver || !typingIndicatorCb.checked) {
            return;
        }
        
        // 防抖：只有用户停止输入500ms才发送
        clearTimeout(typingTimeout);
        typingTimeout = setTimeout(() => {
            wsClient.sendTypingIndicator(currentReceiver);
        }, 500);
    }

    // 添加联系人
    function addFriend() {
        const friendName = newFriendInput.value.trim();
        if (!friendName) {
            return;
        }
        
        if (friends.includes(friendName)) {
            addLog('警告', `${friendName} 已在联系人列表中`);
            return;
        }
        
        // 添加到联系人列表
        friends.push(friendName);
        refreshFriendList();
        
        // 清空输入框
        newFriendInput.value = '';
        
        addLog('信息', `已添加联系人: ${friendName}`);
    }

    // 刷新联系人列表
    function refreshFriendList() {
        friendList.innerHTML = '';
        
        friends.forEach(friendName => {
            const li = document.createElement('li');
            li.className = 'friend-item';
            if (currentReceiver === friendName) {
                li.classList.add('active');
            }
            
            // 创建联系人项内容
            const statusIndicator = document.createElement('div');
            statusIndicator.className = 'status-indicator status-offline';
            
            li.innerHTML = `
                <div class="d-flex align-items-center">
                    <div class="status-indicator status-offline" data-username="${friendName}"></div>
                    <span>${friendName}</span>
                </div>
                <div class="unread-count"></div>
            `;
            
            // 点击事件
            li.addEventListener('click', () => {
                selectFriend(friendName);
            });
            
            friendList.appendChild(li);
        });
    }

    // 选择联系人
    function selectFriend(friendName) {
        currentReceiver = friendName;
        receiverNameSpan.textContent = friendName;
        
        // 更新UI
        refreshFriendList();
        chatCard.style.display = 'block';
        welcomeCard.style.display = 'none';
        
        // 清空消息容器
        messageContainer.innerHTML = '';
        
        // 显示会话历史
        if (conversations[friendName]) {
            conversations[friendName].forEach(msg => {
                displayMessage(msg);
            });
        }
        
        // 清除未读提示
        const friendItem = document.querySelector(`.friend-item:has([data-username="${friendName}"])`);
        if (friendItem) {
            const unreadCount = friendItem.querySelector('.unread-count');
            if (unreadCount) {
                unreadCount.textContent = '';
            }
        }
        
        // 聚焦到输入框
        messageInput.focus();
    }

    // 显示消息
    function displayMessage(message) {
        const isOutgoing = message.fromUser === wsClient.username;
        const messageElement = document.createElement('div');
        messageElement.className = 'message-item';
        messageElement.setAttribute('data-id', message.messageId);
        
        const date = new Date(message.timestamp);
        const timeString = date.toLocaleTimeString();
        
        let statusText = '';
        let statusClass = '';
        
        if (isOutgoing) {
            statusText = message.read ? '已读' : '已发送';
            statusClass = message.read ? 'text-success' : 'text-muted';
        }
        
        messageElement.innerHTML = `
            <div class="message-header">
                <span class="message-sender">${isOutgoing ? '我' : message.fromUser}</span>
                <span class="message-time">${timeString}</span>
            </div>
            <div class="message-content ${isOutgoing ? 'message-outgoing' : 'message-incoming'}">
                ${message.content}
                ${isOutgoing ? `<div class="message-status ${statusClass}" style="font-size: 0.7em; text-align: right;">${statusText}</div>` : ''}
            </div>
        `;
        
        messageContainer.appendChild(messageElement);
        messageContainer.scrollTop = messageContainer.scrollHeight;
    }

    // 更新好友状态
    function updateFriendStatus(friendName, isOnline) {
        const statusIndicator = document.querySelector(`.status-indicator[data-username="${friendName}"]`);
        if (statusIndicator) {
            statusIndicator.className = `status-indicator ${isOnline ? 'status-online' : 'status-offline'}`;
        }
    }

    // 标记有未读消息的好友
    function highlightFriendWithUnread(friendName) {
        const friendItem = document.querySelector(`.friend-item:has([data-username="${friendName}"])`);
        if (friendItem) {
            const unreadCount = friendItem.querySelector('.unread-count');
            if (unreadCount) {
                let count = parseInt(unreadCount.textContent) || 0;
                unreadCount.textContent = count + 1;
                unreadCount.style.backgroundColor = '#4a6fdc';
                unreadCount.style.color = 'white';
                unreadCount.style.borderRadius = '50%';
                unreadCount.style.padding = '2px 6px';
                unreadCount.style.fontSize = '0.8em';
            }
        }
    }

    // 添加日志
    function addLog(level, message) {
        const logItem = document.createElement('div');
        logItem.className = 'message-item animate-fade-in';
        
        const timeStr = new Date().toLocaleTimeString();
        let levelClass = '';
        
        switch (level.toLowerCase()) {
            case '错误':
                levelClass = 'text-danger';
                break;
            case '成功':
                levelClass = 'text-success';
                break;
            case '信息':
                levelClass = 'text-muted';
                break;
            case '收到':
                levelClass = 'text-success';
                break;
            default:
                levelClass = '';
        }
        
        logItem.innerHTML = `
            <div class="message-header">
                <span class="message-sender ${levelClass}">[${level}]</span>
                <span class="message-time">${timeStr}</span>
            </div>
            <div class="message-content">${message}</div>
        `;
        
        connectionLogs.appendChild(logItem);
        connectionLogs.scrollTop = connectionLogs.scrollHeight;
    }

    // 清空日志
    function clearLogs() {
        connectionLogs.innerHTML = '';
    }

    // 初始化页面
    document.addEventListener('DOMContentLoaded', init);
    </script>
</body>
</html> 